package com.shop.loan.service.impl;

import cn.hutool.core.util.IdcardUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.shop.loan.mapper.*;
import com.shop.loan.model.common.Constant;
import com.shop.loan.model.entity.*;
import com.shop.loan.model.enums.ChannelType;
import com.shop.loan.model.enums.UserStatus;
import com.shop.loan.model.vo.YingCaiUserInfoVo;
import com.shop.loan.redis.RedisCache;
import com.shop.loan.redis.RedisUtil;
import com.shop.loan.service.AsyncService;
import com.shop.loan.service.CiWeiService;
import com.shop.loan.service.LiHuoService;
import com.shop.loan.util.AMapUtil;
import com.shop.loan.util.RsaUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;

@Slf4j
@Service
public class AsyncServiceImpl implements AsyncService {

    @Resource
    AMapUtil aMapUtil;

    @Resource
    LoanOrderByMybatisMapper loanOrderByMybatisMapper;

    @Resource
    OperateLogByMybatisMapper operateLogByMybatisMapper;

    @Resource
    ArNotifyLogMybatisMapper arNotifyLogMybatisMapper;

    @Resource
    RedisUtil redisUtil;

    @Lazy
    @Resource
    CiWeiService ciWeiService;

    @Lazy
    @Resource
    LiHuoService liHuoService;

    @Resource
    UserByMybatisMapper userByMybatisMapper;

    @Resource
    UserAuthLogByMybatisMapper userAuthLogByMybatisMapper;

    @Resource
    UserContactByMybatisMapper userContactByMybatisMapper;

    @Value("${api.ciwei.channelId}")
    private Long channelIdByCiWei;

    @Value("${api.lihuo.channelId}")
    private Long channelIdByLiHuo;

    @Value("${api.yc.channelId}")
    private Long channelIdByYc;


    @Value("${api.yc.getOrderUrl}")
    private String getOrderUrl;

    @Value("${api.yc.productCid}")
    private String productCid;

    //盈彩公钥
    @Value("${api.yc.publicKey}")
    private String publicKey;

    //盈彩平台自己私钥
    @Value("${api.yc.s_privateKey}")
    private String s_privateKey;

    @Async
    public void updateLocation(Long orderId, String location) {
        if (!StringUtils.hasText(location)) {
            return;
        }
        log.warn("准备更新用户下单定位 订单:{},经纬度:{}", orderId, location);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String locationAddressInfo = aMapUtil.getInfoByLocation(location);
        if (StringUtils.hasLength(locationAddressInfo)) {
            LoanOrderByMybatis userOrderByMybatis = new LoanOrderByMybatis();
            userOrderByMybatis.setId(orderId);
            userOrderByMybatis.setLocationAddress(locationAddressInfo);
            loanOrderByMybatisMapper.updateByPrimaryKeySelective(userOrderByMybatis);
        }
    }


    @Async
    public void sendNotify(ArNotifyLogMybatisWithBLOBs arNotifyLogMybatis, Long logId) {
        if (arNotifyLogMybatis == null || arNotifyLogMybatis.getId() == null) {
            arNotifyLogMybatis = arNotifyLogMybatisMapper.selectByPrimaryKey(logId);
        }
        if (arNotifyLogMybatis == null || arNotifyLogMybatis.getId() == null) {
            return;
        }
        String resultStr = HttpRequest.post(arNotifyLogMybatis.getUrl()).timeout(Constant.httpTimeOut * 1000).body(arNotifyLogMybatis.getReqParam()).execute().body();
        log.info("发送回调-请求:{},参数:{},返回:{}", arNotifyLogMybatis.getUrl(), arNotifyLogMybatis.getReqParam(), resultStr);
        if (StringUtils.hasLength(resultStr) && JSON.isValidObject(resultStr)) {
            JSONObject res = JSON.parseObject(resultStr);
            ArNotifyLogMybatisWithBLOBs update = new ArNotifyLogMybatisWithBLOBs();
            update.setId(arNotifyLogMybatis.getId());
            update.setResResult(res.toJSONString());
            if (res.containsKey("code") && (res.getInteger("code") == 0 || res.getInteger("code") == 200)) {
                //成功
                update.setStatus(true);
                update.setSuccessTime(new Date());
            } else {
                update.setStatus(false);
                redisUtil.hincrby(RedisCache.arNotifyFailNum, arNotifyLogMybatis.getId() + "", 1L);
                if (Long.parseLong(redisUtil.hget(RedisCache.arNotifyFailNum, arNotifyLogMybatis.getId() + "")) < 5) {
                    //失败次数超过5次 则不再发送
                    redisUtil.lpush(RedisCache.arNotifyQueue, arNotifyLogMybatis.getId() + "");
                }
            }
            arNotifyLogMybatisMapper.updateByPrimaryKeySelective(update);
        }
    }

    @Async
    @Override
    public void getYingCaiOrderInfo(String applyId) {
        try {
            Thread.sleep(1000);

            JSONObject paramJs = new JSONObject();
            paramJs.put("applyId", applyId);
            paramJs.put("productCid", productCid);

            JSONObject signParamJs = RsaUtil.encodeParam(paramJs, publicKey, s_privateKey);
            signParamJs.put("productCid", productCid);
            String resultStr = HttpRequest.post(getOrderUrl)
                    .timeout(Constant.httpTimeOut * 1000)
                    .body(signParamJs.toJSONString())
                    .execute()
                    .body();
            log.info("【盈彩】获取用户信息-请求:{},明文:{}，密文:{},返回:{}", getOrderUrl, paramJs, signParamJs, resultStr);
            if (StringUtils.hasLength(resultStr) && JSON.isValidObject(resultStr)) {
                JSONObject res = JSON.parseObject(resultStr);
                if (res.containsKey("content") && res.containsKey("sign")) {
                    JSONObject backParamJs = RsaUtil.decodeParam(res, publicKey, s_privateKey);
                    if ("0000".trim().equals(backParamJs.getString("code"))) {
                        JSONObject dataJs = backParamJs.getJSONObject("data");

                        YingCaiUserInfoVo arParamVo = JSON.parseObject(dataJs.toJSONString(), YingCaiUserInfoVo.class);
                        UserByMybatis userByMybatis = userByMybatisMapper.selectByMobile(arParamVo.getUserPhone());
                        if (userByMybatis == null || userByMybatis.getId() == null) {
                            //1、插入用户信息
                            UserByMybatis user = new UserByMybatis();
                            user.setIdentityAuthStatus(true);
                            user.setContactAuthStatus(true);
                            user.setBankAuthStatus(false);
                            user.setMobile(arParamVo.getUserPhone());
                            user.setMachineStatus(true);
                            user.setUserStatus(UserStatus.normal.getType());
                            user.setCreateOrder(false);
                            user.setOrderEndNum(0);
                            user.setGender(arParamVo.getGender());
                            user.setAge(IdcardUtil.getAgeByIdCard(arParamVo.getUserCard()));
                            user.setIsDelete(false);
                            user.setCreateTime(new Date());
                            user.setName(arParamVo.getName());
                            user.setChannelId(channelIdByYc);
                            user.setRegisterIp(arParamVo.getCreateIp());
                            user.setCardAddress(arParamVo.getCardAddress());
                            user.setCardName(arParamVo.getName());
                            user.setCardNum(arParamVo.getUserCard());
                            user.setIdCardPicFront(arParamVo.getCardImgFront());
                            user.setIdCardPicBack(arParamVo.getCardImgBack());
                            redisUtil.hset(RedisCache.registerMobileMap, arParamVo.getUserPhone(), "1");
                            userByMybatisMapper.insertSelective(user);

                            //2、插入认证记录
                            UserAuthLogByMybatis userAuthLogByMybatis = new UserAuthLogByMybatis();
                            userAuthLogByMybatis.setUserId(user.getId());
                            userAuthLogByMybatis.setIdCardPicBack(arParamVo.getCardImgBack());
                            userAuthLogByMybatis.setIdCardPicFront(arParamVo.getCardImgFront());
                            userAuthLogByMybatis.setCardName(arParamVo.getName());
                            userAuthLogByMybatis.setCardNum(arParamVo.getUserCard());
//        {"validity":{"birthday":true,"number":true,"address":true,"sex":true,"name":true},"info":{"number":"352203199210236314","address":"福建省福鼎市水北村路外16号","month":"10","nation":"回","year":"1992","sex":"男","name":"丁迪朝","day":"23"}}
                            JSONObject OcrInfoByFrontJs = new JSONObject();
                            OcrInfoByFrontJs.put("validity", new JSONObject());
                            JSONObject OcrInfoByFrontInfo = new JSONObject();
                            OcrInfoByFrontInfo.put("number", arParamVo.getUserCard());
                            OcrInfoByFrontInfo.put("address", arParamVo.getCardAddress());
                            OcrInfoByFrontInfo.put("name", arParamVo.getName());
                            OcrInfoByFrontJs.put("info", OcrInfoByFrontInfo);
                            userAuthLogByMybatis.setOcrInfoByFront(OcrInfoByFrontJs.toJSONString());
//        {"validity":{"authority":true,"timelimit":true},"info":{"authority":"福鼎市公安局","timelimit":"20200915-20400915"}}
                            JSONObject OcrInfoByBackJs = new JSONObject();
                            OcrInfoByBackJs.put("validity", new JSONObject());
                            JSONObject OcrInfoByBackInfo = new JSONObject();
                            OcrInfoByBackInfo.put("authority", arParamVo.getSignOrg());
                            OcrInfoByBackInfo.put("timelimit", arParamVo.getTermDate().replaceAll("\\.", ""));
                            OcrInfoByBackJs.put("info", OcrInfoByBackInfo);
                            userAuthLogByMybatis.setOcrInfoByBack(OcrInfoByBackJs.toJSONString());
                            userAuthLogByMybatis.setAuthUrl(ChannelType.yingcai.getType());
                            userAuthLogByMybatis.setAuthFlowId(ChannelType.yingcai.getType() + user.getId() + System.currentTimeMillis());
                            userAuthLogByMybatis.setCreateTime(new Date());
                            userAuthLogByMybatis.setIdCardAddress(arParamVo.getCardAddress());
                            userAuthLogByMybatis.setFacePhoto(arParamVo.getFaceImg());
                            userAuthLogByMybatisMapper.insertSelective(userAuthLogByMybatis);

                            //3、插入紧急联系人
                            if (StringUtils.hasLength(arParamVo.getRelations())) {
                                JSONArray relations = JSON.parseArray(arParamVo.getRelations());
                                for (Object relation : relations) {
                                    JSONObject item = JSON.parseObject(JSON.toJSONString(relation));
                                    if (item.containsKey("name") && item.containsKey("phone") && item.containsKey("relation")) {
                                        UserContactByMybatis userContactByMybatis1 = new UserContactByMybatis();
                                        userContactByMybatis1.setName(item.getString("name"));
                                        userContactByMybatis1.setMobile(item.getString("phone"));
                                        userContactByMybatis1.setRelation(getRelationByStr(item.getString("relation")));
                                        userContactByMybatis1.setCreateTime(new Date());
                                        userContactByMybatis1.setUserId(user.getId());
                                        userContactByMybatisMapper.insertSelective(userContactByMybatis1);
                                    }
                                }
                            }
                        }
                        return;
                    }
                }
            }
            redisUtil.lpush(RedisCache.yingCaiApplyIdQueue, applyId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Integer getRelationByStr(String relation) {
        if (!StringUtils.hasLength(relation)) {
            return 9;
        }

        if ("F1001".trim().equals(relation)) {
            //父亲
            return 1;
        } else if ("F1002".trim().equals(relation)) {
            //母亲
            return 1;
        } else if ("F1003".trim().equals(relation)) {
            //配偶
            return 5;
        } else if ("F1004".trim().equals(relation)) {
            //朋友
            return 4;
        } else if ("F1005".trim().equals(relation)) {
            //同事
            return 8;
        } else if ("F1006".trim().equals(relation)) {
            //亲属
            return 6;
        } else if ("F1007".trim().equals(relation)) {
            //子女
            return 2;
        } else if ("F1008".trim().equals(relation)) {
            //同学
            return 7;
        }
        return 9;
    }


    /**
     * 修改操作日志（密码不记录）
     *
     * @param requestPath
     * @param operateUser
     * @param reqMethod
     * @param reqAddr
     */
    @Async
    public void updateOpLog(String requestPath, String operateUser, String reqMethod, String reqAddr) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (!requestPath.contains("/operator")) {
            return;
        }
        OperateLogByMybatis operateLogByMybatis = new OperateLogByMybatis();
        operateLogByMybatis.setOperateUser(operateUser);
        operateLogByMybatis.setReqMethod(reqMethod);
        operateLogByMybatis.setReqAddr(reqAddr);
        OperateLogByMybatis log = operateLogByMybatisMapper.selectByLastLog(operateLogByMybatis);
        if (log != null && log.getId() != null) {
            JSONObject jsonObject = JSON.parseObject(log.getReqParam());
            if (jsonObject.containsKey("param")) {
                JSONObject param = jsonObject.getJSONObject("param");
                if (param != null) {
                    param.remove("password");
                    param.remove("password2");
                    param.remove("opPassword");
                    param.remove("oldPassword");
                    param.remove("newPassword");
                    jsonObject.put("param", param);
                }
            }
            jsonObject.remove("password");
            jsonObject.remove("password2");
            jsonObject.remove("opPassword");
            jsonObject.remove("oldPassword");
            jsonObject.remove("newPassword");
            log.setReqParam(jsonObject.toJSONString());
            int index = operateLogByMybatisMapper.updateByPrimaryKeyWithBLOBs(log);
        }
    }


    @Async
    public void notifyCheck(Long orderId) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /**
         * 订单状态更新 给渠道发送回执
         */
        LoanOrderByMybatis loanOrderByMybatis = loanOrderByMybatisMapper.selectByPrimaryKey(orderId);
        if (loanOrderByMybatis == null || loanOrderByMybatis.getIsDelete()) {
            return;
        }
//        if (loanOrderByMybatis.getOrderNum() == null || loanOrderByMybatis.getOrderNum() > 1) {
//            //第二单后不再推送
//            return;
//        }
        UserByMybatis userByMybatis = userByMybatisMapper.selectByPrimaryKey(loanOrderByMybatis.getUserId());
        if (userByMybatis == null) {
            return;
        }
        if (userByMybatis.getChannelId() == null) {
            return;
        }

        if (userByMybatis.getChannelId() == channelIdByCiWei.longValue()) {
            ciWeiService.notifyOrderStatus(loanOrderByMybatis, userByMybatis);
        } else if (userByMybatis.getChannelId() == channelIdByLiHuo.longValue()) {
            if (StringUtils.hasLength(loanOrderByMybatis.getOtherApplyNo())) {
                liHuoService.notifyOrderStatus(loanOrderByMybatis, userByMybatis);
            }
        }
    }


}
